import sys
import datetime
import threading
import cv2
import numpy as np
import socket
from PyQt5 import QtCore, QtWidgets, QtGui
from PyQt5.QtWidgets import QMainWindow
import uvicorn
from fastapi import FastAPI, Body, Request
from fastapi.responses import HTMLResponse
import base64
import ddddocr
from io import BytesIO
from PIL import Image
from PyQt5.QtCore import QUrl
from PyQt5.QtGui import QDesktopServices


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(666, 667)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setLayoutDirection(QtCore.Qt.LeftToRight)
        self.centralwidget.setAutoFillBackground(False)
        self.centralwidget.setObjectName("centralwidget")
        self.tabWidget = QtWidgets.QTabWidget(self.centralwidget)
        self.tabWidget.setGeometry(QtCore.QRect(10, 10, 651, 631))
        self.tabWidget.setLayoutDirection(QtCore.Qt.LeftToRight)
        self.tabWidget.setTabShape(QtWidgets.QTabWidget.Rounded)
        self.tabWidget.setObjectName("tabWidget")
        self.tab_1 = QtWidgets.QWidget()
        self.tab_1.setObjectName("tab_1")
        self.label = QtWidgets.QLabel(self.tab_1)
        self.label.setGeometry(QtCore.QRect(10, 20, 71, 51))
        self.label.setObjectName("label")
        self.text_IPAddress = QtWidgets.QPlainTextEdit(self.tab_1)
        self.text_IPAddress.setGeometry(QtCore.QRect(70, 30, 161, 31))
        self.text_IPAddress.setStyleSheet("")
        self.text_IPAddress.setObjectName("text_IPAddress")
        self.text_Port = QtWidgets.QPlainTextEdit(self.tab_1)
        self.text_Port.setGeometry(QtCore.QRect(280, 30, 81, 31))
        self.text_Port.setObjectName("text_Port")
        self.label_2 = QtWidgets.QLabel(self.tab_1)
        self.label_2.setGeometry(QtCore.QRect(240, 10, 71, 71))
        self.label_2.setObjectName("label_2")
        self.text_Log = QtWidgets.QPlainTextEdit(self.tab_1)
        self.text_Log.setGeometry(QtCore.QRect(10, 90, 621, 441))
        self.text_Log.setStyleSheet("color: rgb(0, 170, 0);")
        self.text_Log.setObjectName("text_Log")
        self.Button_Start = QtWidgets.QPushButton(self.tab_1)
        self.Button_Start.setGeometry(QtCore.QRect(430, 30, 93, 28))
        self.Button_Start.setObjectName("Button_Start")
        self.Button_Stop = QtWidgets.QPushButton(self.tab_1)
        self.Button_Stop.setGeometry(QtCore.QRect(530, 30, 93, 28))
        self.Button_Stop.setObjectName("Button_Stop")
        self.pushButton = QtWidgets.QPushButton(self.tab_1)
        self.pushButton.setGeometry(QtCore.QRect(10, 550, 131, 41))
        self.pushButton.setObjectName("pushButton")
        self.pushButton_2 = QtWidgets.QPushButton(self.tab_1)
        self.pushButton_2.setGeometry(QtCore.QRect(500, 550, 131, 41))
        self.pushButton_2.setObjectName("pushButton_2")
        self.tabWidget.addTab(self.tab_1, "")
        self.tab_2 = QtWidgets.QWidget()
        self.tab_2.setObjectName("tab_2")
        self.label_3 = QtWidgets.QLabel(self.tab_2)
        self.label_3.setGeometry(QtCore.QRect(0, 0, 561, 611))
        self.label_3.setTextFormat(QtCore.Qt.MarkdownText)
        self.label_3.setObjectName("label_3")
        self.tabWidget.addTab(self.tab_2, "")
        MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)
        self.Button_Start.clicked.connect(self.start_button_clicked)
        self.Button_Stop.clicked.connect(self.stop_button_clicked)
        self.pushButton.clicked.connect(self.button_clicked)
        self.pushButton_2.clicked.connect(self.button_2_clicked)

        self.retranslateUi(MainWindow)
        self.tabWidget.setCurrentIndex(0)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def start_button_clicked(self):
        ip = self.text_IPAddress.toPlainText()
        port = int(self.text_Port.toPlainText())


        @api.post("/identify_GeneralCAPTCHA", summary='识别图片内文字',
                  description='普通图片验证码识别，上传图片的Base64编码',
                  tags=['图片验证码识别'])
        async def identify_GeneralCAPTCHA(request: Request,
                                          ImageBase64: str = Body(..., title='验证码图片Bse64文本', embed=True)):
            client_ip = request.client.host
            current_time = datetime.datetime.now().strftime("%H:%M:%S")
            log_text = f"{current_time} : {client_ip} Accessing - WebApi - /identify_GeneralCAPTCHA"
            ui.text_Log.appendPlainText(log_text)
            base64_data = base64.b64decode(ImageBase64)
            ocr = ddddocr.DdddOcr(show_ad=False)
            res = ocr.classification(base64_data)
            hostname = socket.gethostname()
            ip = socket.gethostbyname(hostname)
            return {"result": res,
                    "BiliBili": "https://space.bilibili.com/37887820",
                    "supports": "http://" + ip + ":" + ui.text_Port.toPlainText() + "/support"}

        @api.post("/identify_ArithmeticCAPTCHA", summary='识别算术验证码',
                  description='算术题验证码识别，上传图片的Base64编码，提供两个返回，自行取值分割文本并识别',
                  tags=['图片验证码识别'])
        async def identify_ArithmeticCAPTCHA(request: Request,
                                             ImageBase64: str = Body(..., title='验证码图片Bse64文本', embed=True)):
            hostname = socket.gethostname()
            ip = socket.gethostbyname(hostname)
            client_ip = request.client.host
            current_time = datetime.datetime.now().strftime("%H:%M:%S")
            log_text = f"{current_time} : {client_ip} Accessing - WebApi - /identify_ArithmeticCAPTCHA"
            ui.text_Log.appendPlainText(log_text)
            base64_data = base64.b64decode(ImageBase64)
            ocr = ddddocr.DdddOcr(show_ad=False)
            res = ocr.classification(base64_data)
            try:
                base64_data = base64.b64decode(ImageBase64)
                ocr = ddddocr.DdddOcr(show_ad=False)
                res = ocr.classification(base64_data)
                operators = ['+', '-', 'x', 'X', '÷']
                operator_found = False
                for operator in operators:
                    if operator in res:
                        operator_found = True
                        break

                if operator_found:
                    operand1, operand2 = res.split(operator)
                    operand2 = operand2[:-1]

                    if operator == '+':
                        solution = int(operand1) + int(operand2)
                    elif operator == '-':
                        solution = int(operand1) - int(operand2)
                    elif operator == 'x' or operator == 'X':
                        solution = int(operand1) * int(operand2)
                    elif operator == '÷':
                        solution = int(operand1) / int(operand2)
                    else:
                        solution = "Calculation error"
                else:
                    solution = "Calculation error"

                return {
                    "solution_result": solution,
                    "raw_result": res,
                    "BiliBili": "https://space.bilibili.com/37887820",
                    "supports": "http://" + ip + ":" + ui.text_Port.toPlainText() + "/support"
                }
            except (ValueError, IndexError, base64.binascii.Error):
                return {
                    "solution_result": "Error",
                    "raw_result": "Error",
                    "BiliBili": "https://space.bilibili.com/37887820",
                    "supports": "http://" + ip + ":" + ui.text_Port.toPlainText() + "/support"
                }

        @api.post("/SliderMode_AloneGap", summary='缺口为滑动的单独图片，返回坐标',
                  description='识别模型1：缺口图片为单独图片',
                  tags=['滑块验证码识别'])
        async def SliderMode_AloneGap(request: Request,
                                      Gap_ImageBase64: str = Body(..., title='滑块缺口图片的Bse64文本', embed=True),
                                      Background_ImageBase64: str = Body(..., title='背景图片的Bse64文本', embed=True)):
            client_ip = request.client.host
            current_time = datetime.datetime.now().strftime("%H:%M:%S")
            log_text = f"{current_time} : {client_ip} Accessing - WebApi - /SliderMode_AloneGap"
            ui.text_Log.appendPlainText(log_text)
            ocr = ddddocr.DdddOcr(show_ad=False)
            res = ocr.slide_match(base64.b64decode(Gap_ImageBase64), base64.b64decode(Background_ImageBase64),
                                  simple_target=True)
            hostname = socket.gethostname()
            ip = socket.gethostbyname(hostname)
            return {"result": res,
                    "BiliBili": "https://space.bilibili.com/37887820",
                    "supports": "http://" + ip + ":" + ui.text_Port.toPlainText() + "/support"}

        @api.post("/SliderMode_Comparison", summary='缺口原图和完整原图识别，无单独滑动的缺口图片，返回坐标',
                  description='识别模型2：一张为有缺口原图，一张为完整原图',
                  tags=['滑块验证码识别'])
        async def SliderMode_Comparison(request: Request,
                                        HaveGap_ImageBase64: str = Body(..., title='拥有缺口图片的Bse64文本',
                                                                        embed=True),
                                        Full_ImageBase64: str = Body(..., title='完整背景图片的Bse64文本', embed=True)):
            client_ip = request.client.host
            current_time = datetime.datetime.now().strftime("%H:%M:%S")
            log_text = f"{current_time} : {client_ip} Accessing - WebApi - /ClickChoice_Txt_CAPTCHA"
            ui.text_Log.appendPlainText(log_text)
            ocr = ddddocr.DdddOcr(det=False, ocr=False)
            res = ocr.slide_comparison(base64.b64decode(HaveGap_ImageBase64), base64.b64decode(Full_ImageBase64))
            hostname = socket.gethostname()
            ip = socket.gethostbyname(hostname)
            return {"result": res,
                    "BiliBili": "https://space.bilibili.com/37887820",
                    "supports": "http://" + ip + ":" + ui.text_Port.toPlainText() + "/support"}

        @api.post("/ClickChoice_Txt_CAPTCHA", summary='文字点选验证码识别，返回坐标', description='点选识别返回坐标',
                  tags=['点选类验证码'])
        async def ClickChoice_CAPTCHA(request: Request,
                                      ClickChoice_ImageBase64: str = Body(..., title='点选图片的Base64编码',
                                                                          embed=True)):
            client_ip = request.client.host
            current_time = datetime.datetime.now().strftime("%H:%M:%S")
            log_text = f"{current_time} : {client_ip} Accessing - WebApi - /ClickChoice_Txt_CAPTCHA"
            ui.text_Log.appendPlainText(log_text)
            ocr1 = ddddocr.DdddOcr(show_ad=False)
            ocr2 = ddddocr.DdddOcr(det=True, show_ad=False)
            res = ocr2.detection(base64.b64decode(ClickChoice_ImageBase64))
            if __name__ == '__main__':
                img = Image.open(BytesIO(base64.b64decode(ClickChoice_ImageBase64)))
                res = ocr2.detection(base64.b64decode(ClickChoice_ImageBase64))
                result = {}
                for box in res:
                    x1, y1, x2, y2 = box

                    result[ocr1.classification(img.crop(box))] = [ x1+(x2-x1)//2，y1+(y2-y1)//2]  # 文字位置
            hostname = socket.gethostname()
            ip = socket.gethostbyname(hostname)
            return {"result": result,
                    "BiliBili": "https://space.bilibili.com/37887820",
                    "supports": "http://" + ip + ":" + ui.text_Port.toPlainText() + "/support"}

        @api.post("/ClickChoice_Ico_CAPTCHA", summary='图标点选验证码，返回坐标', description='点选识别返回坐标',
                  tags=['点选类验证码'])
        async def ClickChoice_CAPTCHA(request: Request,
                                      ClickChoiceCAPTCHA_Ico: str = Body(..., title='ico图标的的Base64编码',
                                                                         embed=True),
                                      Ico_ClickChoiceCAPTCHA: str = Body(..., title='点选验证码图片Base64编码',
                                                                         embed=True)):
            client_ip = request.client.host
            current_time = datetime.datetime.now().strftime("%H:%M:%S")
            log_text = f"{current_time} : {client_ip} Accessing - WebApi - /ClickChoice_Ico_CAPTCHA"
            ui.text_Log.appendPlainText(log_text)
            ocr = ddddocr.DdddOcr(show_ad=False)
            res = ocr.slide_match(base64.b64decode(ClickChoiceCAPTCHA_Ico), base64.b64decode(Ico_ClickChoiceCAPTCHA),
                                  simple_target=True)
            hostname = socket.gethostname()
            ip = socket.gethostbyname(hostname)
            return {"result": res,
                    "BiliBili": "https://space.bilibili.com/37887820",
                    "supports": "http://" + ip + ":" + ui.text_Port.toPlainText() + "/support"}

        @api.post("/api.TargetReconnoitre", summary='侦察图片目标',
                  description='上传图片的Base64编码，返回每个目标的xywh和中心点', tags=['Icon侦察'])
        async def TargetReconnoitre(request: Request, have_Ico_Image: str = Body(..., title='图片Base64', embed=True)):
            client_ip = request.client.host
            current_time = datetime.datetime.now().strftime("%H:%M:%S")
            log_text = f"{current_time} : {client_ip} Accessing - WebApi - /api.TargetReconnoitre"
            ui.text_Log.appendPlainText(log_text)
            if __name__ == '__main__':
                img_data = base64.b64decode(have_Ico_Image)
                # 使用numpy数组来表示图像数据
                img_array = np.frombuffer(img_data, dtype=np.uint8)
                # 解码图像
                img = cv2.imdecode(img_array, flags=cv2.IMREAD_COLOR)
                gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
                # 进行 Canny 边缘检测
                edges = cv2.Canny(gray, 50, 150)
                # 使用闭操作填充边缘内部的空洞
                kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
                closed = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
                # 查找轮廓
                contours, _ = cv2.findContours(closed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
                # 存储每个 icon 的信息
                icons = []
                # 在原图上绘制轮廓并记录每个 icon 的信息
                for contour in contours:
                    # 计算轮廓的边界框
                    x, y, w, h = cv2.boundingRect(contour)
                    # 计算轮廓的面积和宽高比
                    area = cv2.contourArea(contour)
                    aspect_ratio = float(w) / h if h != 0 else 0
                    # 如果轮廓面积过小或宽高比不合适，则忽略该轮廓
                    if area < 100 or aspect_ratio < 0.5 or aspect_ratio > 2:
                        continue

                    # 记录 icon 的信息
                    icon = {
                        'x': x,
                        'y': y,
                        'w': w,
                        'h': h,
                        'center_x': x + w / 2,
                        'center_y': y + h / 2
                    }
                    icons.append(icon)

                # 将结果封装成字典格式输出
                result = {
                    'icons': icons
                }
            hostname = socket.gethostname()
            ip = socket.gethostbyname(hostname)
            return {"result": result, "BiliBili": "https://space.bilibili.com/37887820",
                    "supports": "http://" + ip + ":" + ui.text_Port.toPlainText() + "/support"}

        @api.post("/api.IconReconnaissance", summary='Icon点选-opencv编写待优化',
                  description='上传icon图标和背景图标，返回每个目标的xywh和中心点，准确率随缘，等待更新',
                  tags=['Icon侦察'])
        async def IcoReconnaissance(request: Request,
                                    Icon_ImageBase64: str = Body(..., title='Icon图标Base64', embed=True),
                                    BackGround_Base64: str = Body(..., title='背景图片base64', embed=True)):
            client_ip = request.client.host
            current_time = datetime.datetime.now().strftime("%H:%M:%S")
            log_text = f"{current_time} : {client_ip} Accessing - WebApi - /api.IconReconnaissance"
            ui.text_Log.appendPlainText(log_text)
            # 从base64编码的字符串读取图像数据
            background_data = base64.b64decode(BackGround_Base64)
            icon_data = base64.b64decode(Icon_ImageBase64)
            # 将图像数据解码为OpenCV的图像格式
            background = cv2.imdecode(np.frombuffer(background_data, dtype=np.uint8), cv2.IMREAD_GRAYSCALE)
            icon = cv2.imdecode(np.frombuffer(icon_data, dtype=np.uint8), cv2.IMREAD_GRAYSCALE)
            # 将icon图标转换为二值图像
            _, icon = cv2.threshold(icon, 128, 255, cv2.THRESH_BINARY)
            # 使用模板匹配技术查找icon图标在背景图片中的位置
            result = cv2.matchTemplate(background, icon, cv2.TM_CCOEFF_NORMED)
            # 找到最佳匹配的位置
            min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
            top_left = max_loc
            bottom_right = (top_left[0] + icon.shape[1], top_left[1] + icon.shape[0])
            # 计算icon的中心点
            center_x = (top_left[0] + bottom_right[0]) // 2
            center_y = (top_left[1] + bottom_right[1]) // 2
            # 输出icon图标在背景图片上的坐标和中心点
            result = {
                'x': top_left[0],
                'y': top_left[1],
                'w': icon.shape[1],
                'h': icon.shape[0],
                'center_x': center_x,
                'center_y': center_y
            }
            hostname = socket.gethostname()
            ip = socket.gethostbyname(hostname)

            return {"result": result,
                    "BiliBili": "https://space.bilibili.com/37887820",
                    "supports": "http://" + ip + ":" + ui.text_Port.toPlainText() + "/support"}

        @api.get("/support", response_class=HTMLResponse, tags=['赞助StupidOCR'],
                 summary='打开网页：http://localhost:6688/support', include_in_schema=False)
        async def support():
            return """
        <html>
           <head>
            <title>赞助作者</title>
           </head>
            <body>
            <h1 align="center">给无业的作者打赏</h1>
            <h3 align="center">微信&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;支付宝</h3>
            <h1 align="center"> <img  src="" >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;    <img  src="" ></h1>
            <hr>
            <h2 align="left"> GitHub： <a href="https://github.com/81NewArk/StupidOCR">https://github.com/81NewArk/StupidOCR</a></h2>
            <h2 align="left"> BiLiBiLi： <a href="https://space.bilibili.com/37887820">https://space.bilibili.com/37887820</a></h2>
            <h2 align="left"> E-Mail  ： 751247667@qq.com</h2>
            </body>
        </html>
                 """

        threading.Thread(target=uvicorn.run, args=(api,), kwargs={"host": ip, "port": port, "reload": False}).start()
        current_time = datetime.datetime.now().strftime("%H:%M:%S")
        log_text = f"{current_time} StupidOCR - 服务已开启，IP地址：{ip}，端口：{port}\n"
        self.text_Log.appendPlainText(log_text)
        self.Button_Start.setEnabled(False)

    def stop_button_clicked(self):
        current_time = datetime.datetime.now().strftime("%H:%M:%S")
        log_text = f"{current_time} StupidOCR - 停止服务\n"
        self.text_Log.appendPlainText(log_text)
        self.Button_Start.setEnabled(True)
        config = uvicorn.Config(api)
        # 停止服务器
        uvicorn.Server(config).stop()

    def button_clicked(self):
        hostname = socket.gethostname()
        ip = socket.gethostbyname(hostname)
        url = QUrl("http://" + ip + ":" + self.text_Port.toPlainText() + "/docs")
        QDesktopServices.openUrl(url)

    def button_2_clicked(self):
        hostname = socket.gethostname()
        ip = socket.gethostbyname(hostname)
        url = QUrl("http://" + ip + ":" + self.text_Port.toPlainText() + "/support")
        QDesktopServices.openUrl(url)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "StupidOCR  v2.0.1  For GUI"))
        self.label.setText(_translate("MainWindow", "IP地址："))
        self.text_IPAddress.setPlainText(_translate("MainWindow", "0.0.0.0"))
        self.text_IPAddress.setPlaceholderText(_translate("MainWindow", "0.0.0.0"))
        self.text_Port.setPlainText(_translate("MainWindow", "6688"))
        self.text_Port.setPlaceholderText(_translate("MainWindow", "6688"))
        self.label_2.setText(_translate("MainWindow", "端口："))
        self.text_Log.setPlainText(_translate("MainWindow", "日志记录"))
        self.text_Log.setPlaceholderText(_translate("MainWindow", "日志记录："))
        self.Button_Start.setText(_translate("MainWindow", "开启"))
        self.Button_Stop.setText(_translate("MainWindow", "关闭"))
        self.pushButton.setText(_translate("MainWindow", "开发文档"))
        self.pushButton_2.setText(_translate("MainWindow", "赞助页面"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_1), _translate("MainWindow", "功能"))
        self.label_3.setText(_translate("MainWindow", "# StupidOCR v2.0.1 For GUI\n"
                                                      "_________________\n"
                                                      "```\n"
                                                      "应用于爬虫，注册，登录等场景的验证码识别\n"
                                                      "快速 便捷 通用的方法提供用户调用，堪称作者开发神器\n"
                                                      "```\n"
                                                      "_________________\n"
                                                      "## 项目说明：\n"
                                                      "\n"
                                                      "\n"
                                                      ">Python开发， 用于验证码识别，<strong>秉承着会HttpPost协议即可调用的原则！</strong>\n"
                                                      "> \n"
                                                      ">支持部署 <strong>本地</strong> 和 <strong>服务器</strong> .\n"
                                                      "> \n"
                                                      "> 内嵌开发者文档：http://127.0.0.1:6688/docs\n"
                                                      "> \n"
                                                      ">成品长期维护，提供源代码，免费使用等特点\n"
                                                      "\n"
                                                      "\n"
                                                      "\n"
                                                      "\n"
                                                      "\n"
                                                      "\n"
                                                      "## 更新内容：\n"
                                                      "* 修复开发者文档部分BUG\n"
                                                      "\n"
                                                      "\n"
                                                      "* 请求异步执行，实现并发\n"
                                                      "\n"
                                                      "\n"
                                                      "* 通用型验证码识别\n"
                                                      "\n"
                                                      "\n"
                                                      "* 算数验证码识别\n"
                                                      "\n"
                                                      "\n"
                                                      "* 独立滑块验证码识别【返回坐标】\n"
                                                      "\n"
                                                      "\n"
                                                      "* 缺口滑块验证码识别【返回坐标】\n"
                                                      "\n"
                                                      "\n"
                                                      "* 文字点选验证码识别【返回坐标】\n"
                                                      "\n"
                                                      "\n"
                                                      "* 图标点选验证码识别【返回坐标】\n"
                                                      "\n"
                                                      "\n"
                                                      "* 图标侦察【返回坐标】\n"
                                                      "\n"
                                                      "\n"
                                                      "* 基于PYQY5的可视化GUI界面\n"
                                                      "\n"
                                                      "\n"
                                                      "## 关于作者\n"
                                                      "**81NewArk【我叫牛二】**"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("MainWindow", "说明"))


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    icon = QtGui.QIcon('Logo_StupidOCR-104-300x300px.ico')
    MainWindow.setWindowIcon(icon)
    api = FastAPI(title='StupidOCR For GUI 开发者文档', version="2.0.1",
                  description='* GitHub <https://github.com/81NewArk/StupidOCR>')
    MainWindow.show()
    sys.exit(app.exec_())
